<?php

namespace Biz\service\wiki\search;


use Biz\model\wiki\WikiBasic;
use Biz\service\wiki\Search;
use Biz\service\wiki\Wiki;
use Doraemon\cache\Wiki\Search as cWikiSearch;
use Doraemon\model\Category;
use Doraemon\pockets\config\IniConfig;
use Doraemon\pockets\constInterface\ABTest\MarkManage;
use Doraemon\service\ABTest\GetTestStrategy as sGetTestStrategy;
use Doraemon\service\es\EsWikiBasic;
use Doraemon\service\MultiContent\MultiContent;
use Doraemon\tools\Curl;
use Doraemon\tools\HhzClient;
use Doraemon\tools\MsgToRobot;
use Doraemon\tools\ParticipleKeyword;
use Biz\model\store\StoreBasic;
use Doraemon\cache\Store;
use GuzzleHttp\RequestOptions;

class Schedule
{
    const SAVE_MAX_PAGE = 30;

    const PAGESIZE = 20;

    private static $seeKey = null;

    //过滤特定测试uids
    const FILTER_CESHI_UIDS = array(
        7219828,
        7227530,
        10276126,
        10305912,
        10305892,
        10306670,
        9081276,
        10310518,
        10310723,
        8976844,
        9509018,
        10326356,
        10345688,
        10345797,
        9244077,
        9503008,
        9222548,
        11332637,
        11355991,
    );

    // 获取 ab 实验 走的策略
    public static function getWikiSearchStrategy()
    {
        $abTest =  sGetTestStrategy::getStrategyByTestId(MarkManage::SEARCH_WIKI_RANK_1);
        $abTest = intval($abTest);

        return $abTest;
    }

    // 设置Wiki 搜索缓存key
    public static function setSeeKey($page, $keyword, $brandId, $sortType)
    {
        $savePageKey = (int)(($page - 1) / self::SAVE_MAX_PAGE) + 1;

        $cahceKey = $keyword . "-" . $savePageKey . "-B" . $brandId."-Sortd-".$sortType;

        $abTest = self::getWikiSearchStrategy();

        $cahceKey = $cahceKey."-ab_test-".$abTest;

        $cahceKey = md5($cahceKey);

        self::$seeKey = $cahceKey;
    }

    // 获取Wiki 搜索缓存key
    public static function getSeeKey()
    {
        return self::$seeKey;
    }

    // 构建搜索条件
    public static function buildSearchParams($keyword, $brandId, $sortType, $start, $pagesize)
    {
        // 分词
        $handleKeyword = ParticipleKeyword::getCommonParticipleKeyword($keyword);

        // 查询分类id
        $handleKeywordArr = explode(",", $handleKeyword);
        array_push($handleKeywordArr, $keyword);
        $selectKeywordArr = array_unique($handleKeywordArr);

        $categoryParams = array(
            "status" => Category::STATUS_NORMAL,
            "cate_name" => $selectKeywordArr
        );

        $categoryInfos = Category::selectByWhere($categoryParams, ["id", "deep"]);
        $firstCategory = array();
        $secondCategory = array();
        $thirdCategory = array();
        $fourCategory = array();

        foreach ($categoryInfos as $categoryInfo) {
            if (isset($categoryInfo["deep"]) && $categoryInfo["deep"] && isset($categoryInfo["id"]) && $categoryInfo["id"]) {
                switch ($categoryInfo["deep"]) {
                    // 一级标签
                    case 1:
                        array_push($firstCategory, $categoryInfo["id"]);
                        break;
                    // 二级标签
                    case 2:
                        array_push($secondCategory, $categoryInfo["id"]);
                        break;
                    // 三级标签
                    case 3:
                        array_push($thirdCategory, $categoryInfo["id"]);
                        break;
                    // 四级标签
                    case 4:
                        array_push($fourCategory, $categoryInfo["id"]);
                        break;
                }
            }
        }

        // 请求参数
        $params = array(
            "origin_keyword" => $keyword,
            "handle_keyword" => $handleKeyword,
            "status" => implode(",", array(
                WikiBasic::STATE_NORMAL,
                WikiBasic::STATE_ONLINE,
                WikiBasic::STATE_PASS,
                WikiBasic::STATE_EDIT_AUDIT,
            )),
//            "wiki_status" => implode(",", array(
//                    Wiki::STATUS_CHECKED
//                )
//            ),
            "brand_id" => $brandId,
            "select_keywords" => implode(",", $selectKeywordArr),
            "start" => $start,
            "page_size" => $pagesize,
            "fl" => "wiki_id",
            "sort" => $sortType,
            "channel_spu_status" => \Biz\model\wiki\Wiki::CHANNEL_SPU_STATUS_ON
        );

        // 过滤uid
        $params["filter_uid"] = implode(",", self::FILTER_CESHI_UIDS);

        if (is_array($firstCategory) && $firstCategory) {
            $params["first_category"] = implode(",", $firstCategory);
        }

        if (is_array($secondCategory) && $secondCategory) {
            $params["second_category"] = implode(",", $secondCategory);
        }

        if (is_array($thirdCategory) && $thirdCategory) {
            $params["third_category"] = implode(",", $thirdCategory);
        }

        if (is_array($fourCategory) && $fourCategory) {
            $params["four_category"] = implode(",", $fourCategory);
        }

        return $params;
    }

    // 构建wiki数据
    public static function searchWikiIds($keyword, $brandId, $sortType, $page, $pagesize)
    {
        $resetPage = self::SAVE_MAX_PAGE * (int)(($page - 1) / self::SAVE_MAX_PAGE) + 1;
        $start = ($resetPage - 1) * self::PAGESIZE;

        $params = self::buildSearchParams($keyword, $brandId, $sortType, $start, $pagesize);

        $result = EsWikiBasic::search($params);

        $isOver = 1;
        $result['rows'] = is_array($result['rows']) && $result['rows'] ? $result['rows'] : array();

        $searchIds = array();
        if (is_array($result['rows']) && $result['rows']) {
            $allSearchIds = array_column($result['rows'], "wiki_id");

            $abTest = self::getWikiSearchStrategy();

            if ($abTest == 2 && $sortType == 0) {
                // 请求 精排 模型
                $config = IniConfig::getConfigSelect(\Doraemon\service\SearchOp\Schedule::COMMON_INI, 'search_opt');
                $wikiSearchRank = $config['wiki_rank_url'];

                Curl::$defaultConfig[RequestOptions::TIMEOUT] = 0.5;

                $allSearchIdsTmp = array();
                foreach ($allSearchIds as $allSearchId) {
                    array_push($allSearchIdsTmp, (string)($allSearchId));
                }

                $postData = array(
                    "query" => $keyword,
                    "wiki_list" => json_encode($allSearchIdsTmp)
                );

                $res = Curl::Request('POST', $wikiSearchRank . "/search_wiki_rank", ['form_params' => $postData]);

                Curl::$defaultConfig[RequestOptions::TIMEOUT] = 1;

                if (($res['json']['code'] == 1) && is_array($res['json']['data']) && $res['json']['data']) {
                    $allSearchIds = $res['json']['data'];
                }
            }

            // 重新计算偏移量
            list($offsetStart, $offsetEnd) = self::getOffset($page);

            $cacheData = array();
            $offset = $start;
            foreach ($allSearchIds as $id) {
                $cacheData[$id] = $offset;
                $offset++;
            }
            if (is_array($cacheData) && $cacheData) {
                // 设置查询缓存
                cWikiSearch::setSearchData(self::getSeeKey(), $cacheData);
                cWikiSearch::setSearchKeyExpire(self::getSeeKey());
            }

            $searchIds = array_slice($allSearchIds, $offsetStart, self::PAGESIZE);
        } else {
            // 当获取不到值时 设置key为空 缓存时间内不再查数据 减少查询次数
            cWikiSearch::setSearchKeyForEmpty(self::getSeeKey());
            cWikiSearch::setSearchKeyExpire(self::getSeeKey());
        }

        if (count($searchIds) >= self::PAGESIZE) {
            $isOver = 0;
        }

        return array($searchIds, $isOver);
    }

    public static function getGoWikiData($page, $sortType, $keyword)
    {
        $searchGoOpBaseUrl = \Doraemon\service\SearchOp\Schedule::getGoSearchOpBaseUrl();
        $searchUrl = $searchGoOpBaseUrl."/api/main_search.v1.Search/WikiSearch";

        $data = array(
            "page" => $page,
            "query" => $keyword,
            "sort_type" => $sortType,
            "pagesize" => self::PAGESIZE,
            "uid" => HhzClient::getUid(),
        );

        Curl::$defaultConfig[RequestOptions::TIMEOUT] = 2;
        $result = Curl::Request('POST', $searchUrl, ['form_params' => $data]);
        Curl::$defaultConfig[RequestOptions::TIMEOUT] = 1;

        $objIds = array();
        $isOver = 1;

        if (($result['json']['code'] == 1) && is_array($result['json']['obj_ids'])) {
            $objIds = isset($result['json']['obj_ids']) && $result['json']['obj_ids'] ? $result['json']['obj_ids'] : [];

            if (is_array($objIds) && $objIds && count($objIds) >= self::PAGESIZE) {
                $isOver = 0;
            }

        } else {
            $data = json_encode([
                'msgtype' => 'text',
                'text' => [
                    'content' => "go search op wiki 新搜索失败，使用老搜索代替",
                    "mentioned_list" => ["xuzhongjie","xiaoyichao"],
                ]
            ], JSON_UNESCAPED_UNICODE);

            MsgToRobot::sendMsg($data, 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=a4538755-98b8-4de3-95db-f550f7d9954e');
        }

        return array($objIds, $isOver);
    }

    // golang wiki 搜索调度
    public static function searchInGo($page, $sortType, $keyword, $brandId, $searchRequestId = "", $passBackData = "", $from = "")
    {
        // 30页截断
        if ($page > 31) {
            return ['is_over' => 1, 'list' => []];
        }

        list($searchIds, $isOver) = self::getGoWikiData($page, $sortType, $keyword);

        if ($searchIds) {
            $list = Wiki::getCompleteWikiList($searchIds, HhzClient::getUid());
            $list = array_values($list);
            $list = Search::addStatSign($list, $keyword, $searchRequestId, $passBackData, $from);

            if (is_array($list) && $list) {
                # 过滤 门店地址 和 当前访问者 的地址不在同一个地方
                $location = new \Biz\tools\Location(HhzClient::getUid());
                $isShowStore = $location->isShowStore();

                if (!$isShowStore) {
                    $list = self::filterStorePublishContent($list);
                }
            }

            return ['is_over' => $isOver, 'list' => $list];
        }

        return ['is_over' => $isOver, 'list' => []];
    }

    // wiki 搜索调度
    public static function search($page, $sortType, $keyword, $brandId, $searchRequestId = "", $passBackData = "", $from = "")
    {
        $isOver = 1;

        // 30页截断
        if ($page > 31) {
            return ['is_over' => 1, 'list' => []];
        }

        self::setSeeKey($page, $keyword, $brandId, $sortType);
        // 判断搜索内容key存不存在
        if (cWikiSearch::SearchKeyExist(self::getSeeKey())) {
            list($offsetStart, $offsetEnd) = self::getOffset($page);

            $searchIds = cWikiSearch::getSearchData(self::getSeeKey(), $offsetStart, $offsetEnd);
            $searchIds = is_array($searchIds) && $searchIds ? $searchIds : array();

            // 取出的内容为空 由于主从缓存删除key有延迟 重新生成值
            if (empty($searchIds)) {
                list($searchIds, $isOver) = self::searchWikiIds($keyword, $brandId, $sortType, $page, self::SAVE_MAX_PAGE * self::PAGESIZE);
            } else {
                $filterSearchIds = array_filter($searchIds);
                if (is_array($filterSearchIds) && $filterSearchIds) {
                    // 用原始的数据进行判断是否没有数据了
                    if (count($searchIds) >= self::PAGESIZE) {
                        $isOver = 0;
                    }
                }
                // 使用过滤的数据进行下面的操作
                $searchIds = $filterSearchIds;
            }
        } else {
            // key不存在开始生成缓存 生成数据
            list($searchIds, $isOver) = self::searchWikiIds($keyword, $brandId, $sortType, $page, self::SAVE_MAX_PAGE * self::PAGESIZE);
        }

        if ($searchIds) {
            $list = Wiki::getCompleteWikiList($searchIds, HhzClient::getUid());
            $list = array_values($list);
            $list = Search::addStatSign($list, $keyword, $searchRequestId, $passBackData, $from);

            if (is_array($list) && $list) {
                # 过滤 门店地址 和 当前访问者 的地址不在同一个地方
                $location = new \Biz\tools\Location(HhzClient::getUid());
                $isShowStore = $location->isShowStore();

                if (!$isShowStore) {
                    $list = self::filterStorePublishContent($list);
                }
            }

            return ['is_over' => $isOver, 'list' => $list];
        }

        return ['is_over' => $isOver, 'list' => []];
    }

    # 过滤 门店地址 和 当前访问者 的地址不在同一个地方
    public static function filterStorePublishContent($list)
    {
        $storeInfos = Store::getAllStoreInfos();
        if (!(is_array($storeInfos) && $storeInfos)) {
            $storeInfos = StoreBasic::getAllNormalStores();
            Store::setAllStoreInfos($storeInfos);
        }

        # 获取门店内容uids
        $storeUids = array();
        if (is_array($storeInfos) && $storeInfos) {
            $storeUids = array_column($storeInfos, "uid");
            $storeUids = array_map("intval", $storeUids);
        }

        $listTmp = array();
        foreach ($list as $item) {
            if (isset($item["store_info"])) {
                if (isset($item["store_info"]["uid"]) && $item["store_info"]["uid"] > 0 &&
                    !in_array(intval($item["store_info"]["uid"]), $storeUids)) {
                    array_push($listTmp, $item);
                }
            } else {
                array_push($listTmp, $item);
            }
        }

        return $listTmp;
    }

    // 获取缓存偏移量
    public static function getOffset($page)
    {
        $showPageSize = self::PAGESIZE;

        $resetPage = ($page - 1) % self::SAVE_MAX_PAGE;
        $start = ($resetPage) * $showPageSize;
        $end = $start + $showPageSize - 1;

        return array(
            $start,
            $end
        );
    }
}